﻿using Ebusiness_UserService.Data;
using Ebusiness_UserService.DomainEvent.User;
using Ebusiness_UserService.Model;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;

namespace Ebusiness_UserService.Repositorys
{
    /// <summary>
    /// 仓储”((Repository)
    ///     仓储负责按照要求从数据库中读取数据以及把领域服务（三层架构中的领域服务）修改的数据保存回数据库。
    /// </summary>
    [Dependency(ServiceLifetime.Transient)]
    public class UserRepository : EfCoreRepository<Ebusiness_UserServiceDbContext, User, Guid>, IUserRepository
    {
        /// <summary>
        /// 默认存储在MemoryDistributedCache Microsoft.Extensions.Caching.Memory
        /// 缓存在本地应用进程内的内存中
        /// </summary>
        public IDistributedCache distributedCache { get; set; }

        public IMediator mediator { get; set; }

        public UserRepository(IDbContextProvider<Ebusiness_UserServiceDbContext> dbContextProvider) : base(dbContextProvider)
        {

        }

        public override async Task<User> InsertAsync(User entity, bool autoSave = false, CancellationToken cancellationToken = default)
        {
            //(await GetDbContextAsync()).users.AddRange(entity);
            return await base.InsertAsync(entity, autoSave, cancellationToken);
        }

        /// <summary>
        /// 作废
        /// </summary>
        /// <param name="phoneNumber"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public async Task AddNewLoginHistoryAsync(PhoneNumber phoneNumber, string msg)
        {
            //User? user = await FindOneAsync(phoneNumber);
            //Guid? userId = null;
            //if (user != null) {
            //    userId = user.Id;
            //}
        }

        public async Task<User?> FindOneAsync(PhoneNumber phoneNumber)
        {
            //var dat = await GetDbContextAsync();
            //Console.WriteLine("xxxxxxxxxxxxxxxx" + dat.GetHashCode());
            //var code = dat.GetHashCode(); //19063697 64096642

            //批量删除修改
            //(await GetDbContextAsync()).users.ExecuteDelete();
            //(await GetDbContextAsync()).users.ExecuteUpdateAsync();

            //获取查询的sql语句 只能查询使用
            //var sql = (await GetDbContextAsync()).users.Include(x => x.userAccessFail).Where(x => x.phoneNumber.Code == phoneNumber.Code && x.phoneNumber.Phone == phoneNumber.Phone).ToQueryString();
            
            return await (await GetDbContextAsync()).users.Include(x => x.userAccessFail).Where(x => x.phoneNumber.Code == phoneNumber.Code && x.phoneNumber.Phone == phoneNumber.Phone).FirstOrDefaultAsync();
            //return await FindAsync(x => x.phoneNumber.Code == phoneNumber.Code && x.phoneNumber.Phone == phoneNumber.Phone);
        }

        public async Task<User?> FindOneAsync(Guid userld)
        {
            return await FindAsync(x => x.Id == userld);
        }

        public async Task<string?> FindPhoneNumberCodeAsync(PhoneNumber phoneNumber)
        {
            string key = $"PhoneNumberCode_{phoneNumber.Phone}_{phoneNumber.Code}";
            var code = await distributedCache.GetStringAsync(key);
            await distributedCache.RemoveAsync(key);
            return code;
        }

        public Task PublishEventAsync(UserAccessResultEvent eventData)
        {
            return mediator.Publish(eventData);
        }

        public Task<string?> RetrievePhoneCodeAsync(PhoneNumber phoneNumber)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 存储验证码
        /// </summary>
        /// <param name="phoneNumber"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public Task SavePhoneCodeAsync(PhoneNumber phoneNumber, string code)
        {
            var options = new DistributedCacheEntryOptions
            {
                // 设置 10 分钟后过期（相对当前时间）
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
            };
            string key = $"PhoneNumberCode_{phoneNumber.Phone}_{phoneNumber.Code}";
            return distributedCache.SetStringAsync(key, code);
        }
    }
}
